package org.codehaus.activemq.message.util;

import EDU.oswego.cs.dl.util.concurrent.ConcurrentHashMap;
import EDU.oswego.cs.dl.util.concurrent.SynchronizedLong;
import java.util.Collection;
import java.util.Iterator;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.codehaus.activemq.capacity.BasicCapacityMonitor;
import org.codehaus.activemq.message.Packet;

public class MemoryBoundedQueueManager extends BasicCapacityMonitor
{
  private static final int OBJECT_OVERHEAD = 50;
  SynchronizedLong totalMemoryUsedSize = new SynchronizedLong(0L);
  private ConcurrentHashMap activeQueues = new ConcurrentHashMap();
  private static final Log log = LogFactory.getLog(MemoryBoundedQueueManager.class);

  public MemoryBoundedQueueManager(String name, long maxSize)
  {
    super(name, maxSize);
  }

  public MemoryBoundedQueue getMemoryBoundedQueue(String name)
  {
    MemoryBoundedQueue result = (MemoryBoundedQueue)this.activeQueues.get(name);
    if (result == null) {
      result = new MemoryBoundedQueue(name, this);
      this.activeQueues.put(name, result);
    }
    return result;
  }

  public void close()
  {
    for (Iterator i = this.activeQueues.values().iterator(); i.hasNext(); ) {
      MemoryBoundedQueue mbq = (MemoryBoundedQueue)i.next();
      mbq.close();
    }
    this.activeQueues.clear();
  }

  public long getTotalMemoryUsedSize()
  {
    return this.totalMemoryUsedSize.get();
  }

  public boolean isFull()
  {
    boolean result = this.totalMemoryUsedSize.get() >= super.getValueLimit();
    return result;
  }

  int incrementMemoryUsed(Packet obj) {
    int size = 50;
    if (obj != null) {
      if (obj.getMemoryUsageReferenceCount() == 0) {
        size += obj.getMemoryUsage();
      }
      obj.incrementMemoryReferenceCount();
    }
    this.totalMemoryUsedSize.add(size);
    super.setCurrentValue(this.totalMemoryUsedSize.get());
    return size;
  }

  int decrementMemoryUsed(Packet obj) {
    int size = 50;
    if (obj != null) {
      obj.decrementMemoryReferenceCount();
      if (obj.getMemoryUsageReferenceCount() == 0) {
        size += obj.getMemoryUsage();
      }
    }
    this.totalMemoryUsedSize.subtract(size);
    super.setCurrentValue(this.totalMemoryUsedSize.get());
    return size;
  }

  protected void finalize() {
    close();
  }

  void removeMemoryBoundedQueue(String name) {
    this.activeQueues.remove(name);
  }
}